﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.Integration;
using System.Xml.Serialization;
using LiveSequence.Common;
using LiveSequence.Common.Context;
using LiveSequence.Dialogs;
using LiveSequence.Interface;
using LiveSequence.Suite.Domain;
using LiveSequence.Suite.Interfaces;
using LiveSequence.Suite.Views;
using LiveSequence.Suite.Properties;
using LiveSequence.Suite.Views;
using WeifenLuo.WinFormsUI.Docking;
using LiveSequence.Common.Graphics;
using LiveSequence.Common.Domain;
using LiveSequence.Common.Presentation;
using LiveSequence.Suite.Helpers;
using LiveSequence.Suite.Interfaces;
using LiveSequence.Suite.Documents;

namespace LiveSequence.Suite
{
  public partial class MainFrame : Form, ISVizDocument
  {
    #region Attributes
    private AssemblyExplorer _assemblyController;
    private ProjectDoc _projectDoc;

    private bool _bIsDirty;
    private string _strFileName;
    private int _iNewFileCounter = 1;

    private string _strFileFilter;
    private string _strFileExtension;

    private Frame _assemblyExplorer;
    private Frame _classView;
    private Frame _projectExplorer;
    private DiagramView _mainView;

    private Frame _callTreeView;
    private Frame _propertyView;
    private Frame _objectInstances;

    private DocManager _docManager;

    private LSMethodCallDiagram _selectedDiagram;
    private WeifenLuo.WinFormsUI.Docking.DockPanel _dockPanel;

    #endregion Attributes

    #region Constructor
    public MainFrame()
    {
      InitializeComponent();
      InitializeComponentEx();

      _docManager = DocManager.Instance;
      _assemblyController = AssemblyExplorer.Instance;

      _projectDoc = new ProjectDoc(new LSProject());
      _bIsDirty = false;

      _strFileExtension = ".ls";
      _strFileFilter = string.Format("{0} Files (*{1})|*{1}|All Files (*.*)|*.*",
        Application.ProductName, FileExtension);

      createViews();

      _docManager.ActiveDocumentChanged += new EventHandler(_docManager_ActiveDocumentChanged);
      
    }

    #endregion Constructor


    private void InitializeComponentEx()
    {
      _dockPanel = new DockPanel();
      _dockPanel.ActiveAutoHideContent = null;
      _dockPanel.Dock = System.Windows.Forms.DockStyle.Fill;
      _dockPanel.Location = new System.Drawing.Point(0, 49);
      _dockPanel.Name = "_dockPanel";
      _dockPanel.RightToLeftLayout = true;
      _dockPanel.Size = new System.Drawing.Size(792, 503);
      _dockPanel.TabIndex = 0;

      _dockPanel.DocumentStyle = DocumentStyle.DockingSdi;

      _maintoolStripContainer.ContentPanel.Controls.Add(_dockPanel);

      _mainView = new DiagramView();
      _mainView.Dock = DockStyle.Fill;
      DockContent dc = new DockContent();
      dc.Controls.Add(_mainView);

      dc.Show(_dockPanel, DockState.Document);

      _mainView.ViewToolStrip.Visible = true;
      _maintoolStripContainer.TopToolStripPanel.Controls.Add(_mainView.ViewToolStrip);


    }

    /// <summary>
    /// Initializes the component ex.
    /// </summary>
    private void createViews()
    {
      Frame dc;
      DockPane rightPane;
      DockPane leftPane;

      dc = FormHelper.CreateDockContent("Assembly Explorer", new AssemblyExplorerView(), Resources.AssemblyExplorer);
      dc.Show(_dockPanel, DockState.DockLeft);
      AddViewMenu(dc);
      _assemblyExplorer = dc;
      leftPane = dc.Pane;

      //dc = FormHelper.CreateDockContent("Class View", new ClassView());
      //dc.Show(leftPane, DockAlignment.Bottom, 0.5);
      //AddViewMenu(dc);
      //_classView = dc;

      dc = FormHelper.CreateDockContent("Project Explorer", new ProjectExplorer());
      dc.Show(leftPane, DockAlignment.Bottom, 0.5);
      AddViewMenu(dc);
      _classView = dc;

      dc = FormHelper.CreateDockContent("Method Call Tree", new MethodCallTreeView(), Resources.FilterMethodCallTree1);
      dc.Show(_dockPanel, DockState.DockRight);
      AddViewMenu(dc);
      _callTreeView = dc;
      dc.Pane.Width = 100;

      dc = FormHelper.CreateDockContent("Object Instances", new ListObjectInstanceView());
      dc.Show(_dockPanel, DockState.DockRight);
      AddViewMenu(dc);
      _objectInstances = dc;
      rightPane = dc.Pane;


      dc = FormHelper.CreateDockContent("Properties", new PropertyView(), Resources.Properties);
      dc.Show(rightPane, DockAlignment.Bottom, 0.5);
      AddViewMenu(dc);
      _propertyView = dc;

      _callTreeView.Activate();

    }

    private void AddViewMenu(Frame dc)
    {
      ToolStripMenuItem mnuItemView = new ToolStripMenuItem(dc.Text);
      mnuItemView.CheckOnClick = true;
      viewMenu.DropDownItems.Add(mnuItemView);
      mnuItemView.Tag = dc;
      mnuItemView.Click += new EventHandler(mnuItemView_Click);
      mnuItemView.Paint += new PaintEventHandler(mnuItemView_Paint);
    }

    void mnuItemView_Paint(object sender, PaintEventArgs e)
    {
      ToolStripMenuItem mnuItemView = sender as ToolStripMenuItem;

      if (mnuItemView != null)
      {
        Frame dc = mnuItemView.Tag as Frame;
        mnuItemView.Checked = !dc.IsHidden;
      }

    }

    /// <summary>
    /// Handles the Click event of the mnuItemView control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    void mnuItemView_Click(object sender, EventArgs e)
    {
      ToolStripMenuItem mnuItem = sender as ToolStripMenuItem;
      if (mnuItem != null)
      {
        Frame dc = mnuItem.Tag as Frame;
        dc.IsHidden = !mnuItem.Checked;
        if (!dc.IsHidden)
        {
          dc.Activate();
        }
      }
    }

    /// <summary>
    /// News the document command.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    private void newDocumentCommand(object sender, EventArgs e)
    {
      if (Clear())
      {
        CreateDocument();
        OnUpdateAllViews(null);
      }
    }

    private void openFileCommand(object sender, EventArgs e)
    {
      OpenFileDialog openDlg = new OpenFileDialog();
      openDlg.Filter = _strFileFilter;
      openDlg.FileName = "";
      openDlg.DefaultExt = FileExtension;
      openDlg.CheckFileExists = true;
      openDlg.CheckPathExists = true;

      DialogResult res = openDlg.ShowDialog();

      if (res == DialogResult.OK)
      {
        if (!(openDlg.FileName).EndsWith(FileExtension) &&
          !(openDlg.FileName).EndsWith(FileExtension.ToUpper()))
          MessageBox.Show("Unexpected file format", Application.ProductName, MessageBoxButtons.OK);
        else
        {
          if (Clear())
          {
            OpenDocument(openDlg.FileName);
            OnUpdateAllViews(null);
          }
        }
      }
    }

    private void CreateDocument()
    {
      _strFileName = string.Format("Project{0}", _iNewFileCounter++);
      _projectDoc = new ProjectDoc(new LSProject());
      _docManager.MasterDocument = _projectDoc;
    }

    private void saveCommand(object sender, EventArgs e)
    {
      bool bSaveDocument = false;
      if (string.IsNullOrEmpty(FileName))
      {
        SaveFileDialog saveFileDialog = new SaveFileDialog();
        saveFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
        saveFileDialog.Filter = _strFileFilter;
        if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
        {
          _strFileName = saveFileDialog.FileName;
          bSaveDocument = true;
        }
      }
      else
      {
        bSaveDocument = true;
      }

      if (bSaveDocument)
      {
        SaveDocument(FileName);
      }

    }

    private void saveAsCommand(object sender, EventArgs e)
    {             
      SaveFileDialog saveFileDialog = new SaveFileDialog();
      saveFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
      saveFileDialog.Filter = _strFileFilter;
      if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
      {
        string strFileName = saveFileDialog.FileName;
        SaveDocument(strFileName);		
      }
    }

    private void ExitToolsStripMenuItem_Click(object sender, EventArgs e)
    {
      this.Close();
    }

    private void CutToolStripMenuItem_Click(object sender, EventArgs e)
    {
    }

    private void CopyToolStripMenuItem_Click(object sender, EventArgs e)
    {
    }

    private void PasteToolStripMenuItem_Click(object sender, EventArgs e)
    {
    }

    private void ToolBarToolStripMenuItem_Click(object sender, EventArgs e)
    {
      mainToolStrip.Visible = toolBarToolStripMenuItem.Checked;
    }

    private void StatusBarToolStripMenuItem_Click(object sender, EventArgs e)
    {
      statusStrip.Visible = statusBarToolStripMenuItem.Checked;
    }

    private void CascadeToolStripMenuItem_Click(object sender, EventArgs e)
    {
      LayoutMdi(MdiLayout.Cascade);
    }

    private void TileVerticalToolStripMenuItem_Click(object sender, EventArgs e)
    {
      LayoutMdi(MdiLayout.TileVertical);
    }

    private void TileHorizontalToolStripMenuItem_Click(object sender, EventArgs e)
    {
      LayoutMdi(MdiLayout.TileHorizontal);
    }

    private void ArrangeIconsToolStripMenuItem_Click(object sender, EventArgs e)
    {
      LayoutMdi(MdiLayout.ArrangeIcons);
    }

    private void CloseAllToolStripMenuItem_Click(object sender, EventArgs e)
    {
      foreach (Form childForm in MdiChildren)
      {
        childForm.Close();
      }
    }

    #region IProjectController Members

    public event EventHandler UpdateView;



    public void CreateDiagram(string strMethodName, string strTypeName, 
                              string strNameSpace, string strAssemblyName
                              )
    {
      
      SequenceData sequenceData = _assemblyController.GetSequenceData(strMethodName, strTypeName, strNameSpace, strAssemblyName);

      LSMethodCallDiagram diagram = new LSMethodCallDiagram(strMethodName, strTypeName, strNameSpace, strAssemblyName, sequenceData);

      _projectDoc.Project.Diagrams.Add(diagram);
      IsDirty = true;

      OnCreateDiagram(diagram);

      SelectedDiagram = diagram;
    }

    private void OnCreateDiagram(LSMethodCallDiagram diagram)
    {
      if(this.UpdateView!=null)
      {
        UpdateView(this, EventArgs.Empty);
      }
    }

    public event EventHandler SelectedDiagramChanged;

    public LSMethodCallDiagram SelectedDiagram
    {
      get
      {
        return _selectedDiagram;
      }
      set
      {
        LSMethodCallDiagram oldSelectedDiagram = _selectedDiagram;
        _selectedDiagram = value;
        if(oldSelectedDiagram!=value)
        {
          OnSelectedDiagramChanged(value);
        }
      }
    }

    private void OnSelectedDiagramChanged(LSMethodCallDiagram diagram)
    {
      if(SelectedDiagramChanged!=null)
      {
        SelectedDiagramChanged(this, EventArgs.Empty);
      }      
    }

    public LSProject Project
    {
      get { return _projectDoc.Project; }
    }

    #endregion


    private void HandleException(Exception ex)
    {
      MessageBox.Show(ex.Message);
    }

    #region ISDIController Members


    public void SaveDocument(string fileName)
    {
      try
      {
        ProjectDoc projectDoc = _docManager.MasterDocument;
        LSProject project = projectDoc.Project;
        Stream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.Write);

        // Serialize an object into the storage medium referenced by 'stream' object.
        System.Runtime.Serialization.IFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
        formatter.Serialize(stream, project);

      }
      catch(Exception ex)
      {
        HandleException(ex);
      }
    }

    public void OpenDocument(string fileName)
    {
      try
      {
        // Read the file back into a stream
        Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);

        // Now create a binary formatter (it is up to you to ensure that code uses the same formatter for serialization
        // and deserialization
        System.Runtime.Serialization.IFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

        // Deserialize the object and use it. Note: Constructors will not be called
        LSProject project = _projectDoc.Project;
        project = (LSProject)formatter.Deserialize(stream);

        ProjectDoc projectDoc = new ProjectDoc(project);


        if (project.Diagrams.Count > 0)
        {
          SelectedDiagram = project.Diagrams[0];
        }
        else
        {
          SelectedDiagram = null;
        }

        _docManager.MasterDocument = projectDoc;
      }
      catch(Exception ex)
      {
        HandleException(ex);
      }

    }

    public void OnUpdateAllViews(IView sender)
    {
      if(UpdateView!=null)
      {
        UpdateView(sender, EventArgs.Empty);
      }


    }

    public void DeleteContents()
    {

    }

    public string FileExtension
    {
      get
      {
        return _strFileExtension;
      }
      set
      {
        ;
      }
    }

    public bool Clear()
    {
      bool bResult = true;
      if (IsDirty)
      {
        DialogResult save = MessageBox.Show("Do you want to Save changes ?", Application.ProductName, MessageBoxButtons.YesNoCancel);
        if (save == DialogResult.Yes)
        {
          saveCommand(null, EventArgs.Empty);
        }
      }
      
      return bResult;
    }

    public bool IsDirty
    {
      get
      {
        return _bIsDirty;
      }

      set
      {
        bool bOldIsDiry = _bIsDirty;
        _bIsDirty = value;
        if(bOldIsDiry != _bIsDirty)
        {
          OnIsDirtyChanged();
        }
      }
    }

    private void OnIsDirtyChanged()
    {
      if(IsDirtyChanged!=null)
      {
        IsDirtyChanged(this, EventArgs.Empty);
      }
    }

    public string FileName
    {
      get { return _strFileName; }
    }

    #endregion

    #region ISDIController Members


    public event EventHandler IsDirtyChanged;

    #endregion

    private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
    {
      AboutBox dialog = new AboutBox();
      dialog.ShowDialog();
    }

    private void printToolStripMenuItem_Click(object sender, EventArgs e)
    {
      System.Windows.Controls.PrintDialog printDialog = new System.Windows.Controls.PrintDialog();
      if (printDialog.ShowDialog().Equals(false))
      {
        return;
      }

      _mainView.Print(printDialog);
      

    }

    private void contentsToolStripMenuItem_Click(object sender, EventArgs e)
    {
      Help.ShowHelp(this, Application.StartupPath + "\\Manual\\Manual.chm");
    }

    #region ISVizDocument Members

    #endregion

    private void MainFrame_Load(object sender, EventArgs e)
    {
      OnUpdateAllViews(null);
    }

    void _docManager_ActiveDocumentChanged(object sender, EventArgs e)
    {

    }

  }
}
